package com.hb.common.service.impl;

import cn.hutool.core.io.FileUtil;
import com.hb.common.constant.Config;
import com.hb.common.dto.Database;
import com.hb.common.dto.DbBackupFile;
import com.hb.common.exception.DbBackupException;
import com.hb.common.service.DatabaseService;
import com.hb.common.service.DbBackupFileService;
import com.hb.common.util.CommonUtil;
import com.hb.common.util.PathPermissions;
import com.hb.common.util.Result;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

@Service
public class DbBackupFileServiceImpl implements DbBackupFileService {

    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private PathPermissions pathPermissions;

    /**
     * 根据数据库id，获取备份文件
     */
    @Override
    public Result<List<DbBackupFile>> selectBackupFiles(Integer id) throws DbBackupException {
        List<DbBackupFile> backupFiles = new ArrayList<>();

        Database database = applicationContext.getBean(DatabaseService.class).selectById(id).getData();
        // 获取存储目录
        String dbBackupPath = pathPermissions.getDbBackupPath(database);
        // 获取目录下的文件
        File[] fileList = FileUtil.ls(dbBackupPath);

        for (File file : fileList) {
            if (FileUtil.isFile(file)) {
                String fileName = FileUtil.getName(file);

                // 文件大小
                long size = FileUtil.size(file);
                String formatFileSize = CommonUtil.formatFileSize(size);

                BasicFileAttributes attributes;
                try {
                    attributes = Files.readAttributes(file.getAbsoluteFile().toPath(), BasicFileAttributes.class);
                } catch (IOException e) {
                    throw new DbBackupException(e);
                }
                Date backupTime = new Date(attributes.lastModifiedTime().toMillis());

                DbBackupFile backupFile = new DbBackupFile();
                backupFile.setId(id);
                backupFile.setFileName(fileName);
                backupFile.setSize(formatFileSize);
                backupFile.setBackupTime(backupTime);

                backupFiles.add(backupFile);
            }
        }
        // 按文件日期倒序显示
        List<DbBackupFile> list = backupFiles.stream().sorted(Comparator.comparing(DbBackupFile::getBackupTime).reversed()).toList();
        return Result.success(list);
    }

    @Override
    public Result<Integer> selectCount(Database database) {
        // 获取存储目录
        String dbBackupPath = pathPermissions.getDbBackupPath(database);
        // 获取目录下的文件
        File[] fileList = FileUtil.ls(dbBackupPath);
        // 文件数量
        int count = 0;
        for (File file : fileList) {
            if (FileUtil.isFile(file)) {
                count ++;
            }
        }
        return Result.success(count);
    }

    /**
     * 删除备份文件
     */
    @Override
    public Result<Boolean> deleteFile(Integer id, String fileName) {
        Database database = applicationContext.getBean(DatabaseService.class).selectById(id).getData();
        String dbBackupPath = pathPermissions.getDbBackupPath(database);
        File file = new File(dbBackupPath, fileName);
        if (file.exists()) {
            boolean deleted = FileUtil.del(file);
            return Result.success(deleted);
        }
        return Result.success(true);
    }

    /**
     * 下载备份文件
     *
     * @param fileName 备份文件名称
     * @param response response
     */
    @Override
    public void downloadFile(Integer id, String fileName, HttpServletResponse response) throws DbBackupException {
        Database database = applicationContext.getBean(DatabaseService.class).selectById(id).getData();
        String dbBackupPath = pathPermissions.getDbBackupPath(database) + fileName;
        File file = new File(dbBackupPath);

        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
             OutputStream out = response.getOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            throw new DbBackupException(e);
        }
    }

    /**
     * 上传数据库程序
     */
    @Override
    public Result<Boolean> uploadDbProgram(MultipartFile file) {
        try {
            if (Config.DB_PROGRAM_ZIP.equals(file.getOriginalFilename())) {
                // 保存文件到目录
                Path filePath = Paths.get(pathPermissions.getConfigPath() + file.getOriginalFilename());
                Files.write(filePath, file.getBytes());
                // 解压
                CommonUtil.unzipDbProgram(pathPermissions.getConfigPath() + file.getOriginalFilename(), pathPermissions.getConfigPath());
                return Result.success("上传成功: " + file.getOriginalFilename(), true);
            } else {
                return Result.fail("请上传正确的数据库程序文件");
            }
        } catch (Exception e) {
            return Result.fail("上传失败: " + e.getMessage());
        }
    }
}
